//
//  MHTableViewController.m
// MiaoCircle
//
//Created by acgera on 2018/4/9.
//  Copyright © 2018年 acgera. All rights reserved.
//

#import "MHCollectionViewController.h"
#import "UIScrollView+MHRefresh.h"


@interface MHCollectionViewController ()<CHTCollectionViewDelegateWaterfallLayout,DZNEmptyDataSetDelegate,DZNEmptyDataSetSource>
/// tableView
@property (nonatomic, readwrite, strong)   MHCollectionView *collectionView;
/// contentInset defaul is (64 , 0 , 0 , 0)
@property (nonatomic, readwrite, assign) UIEdgeInsets contentInset;
/// 视图模型
@property (nonatomic, readonly, strong) MHTableViewModel *viewModel;
@end

@implementation MHCollectionViewController

@dynamic viewModel;

- (void)dealloc
{
    // set nil
//    _tableView.dataSource = nil;
//    _tableView.delegate = nil;
}

/// init
- (instancetype)initWithViewModel:(MHTableViewModel *)viewModel {
    self = [super initWithViewModel:viewModel];
    if (self) {
        if ([viewModel shouldRequestRemoteDataOnViewDidLoad]) {
            @weakify(self)
            [[self rac_signalForSelector:@selector(viewDidLoad)] subscribeNext:^(id x) {
                @strongify(self)
                /// 请求第一页的网络数据
                [self.viewModel.requestRemoteDataCommand execute:@1];
            }];
        }
    }
    return self;
}


- (void)viewDidLoad
{
    [super viewDidLoad];
    // 设置子控件
    [self _su_setupSubViews];
    
}

/// override
- (void)bindViewModel
{
    [super bindViewModel];
    
    /// observe viewModel's dataSource
    @weakify(self)
    [[RACObserve(self.viewModel, dataSource)
      deliverOnMainThread]
     subscribeNext:^(id x) {
         @strongify(self)
         // 刷新数据
         [self reloadData];
     }];
    
    /// 隐藏emptyView
    [self.viewModel.requestRemoteDataCommand.executing subscribeNext:^(NSNumber *executing) {
        @strongify(self)
        UIView *emptyDataSetView = [self.collectionView.subviews.rac_sequence objectPassingTest:^(UIView *view) {
            return [NSStringFromClass(view.class) isEqualToString:@"DZNEmptyDataSetView"];
        }];
        emptyDataSetView.alpha = 1.0 - executing.floatValue;
    }];
    
    
//    [self.viewModel.requestRemoteDataCommand.executionSignals.switchToLatest subscribeNext:^(id _) {
//        @strongify(self);
//        /// 有网络
//        self.viewModel.disableNetwork = NO;
//    }];
//    
//    [self.viewModel.requestRemoteDataCommand.errors subscribeNext:^(id _) {
//        @strongify(self);
//        /// 有无网络
//        self.viewModel.disableNetwork = !self.viewModel.services.client.reachabilityManager.reachable;
//    }];
}

#pragma mark - 设置子控件
/// setup add `_su_` avoid sub class override it
- (void)_su_setupSubViews{
    // set up tableView
    CHTCollectionViewWaterfallLayout *layout = [[CHTCollectionViewWaterfallLayout alloc] init];
    
    layout.sectionInset = UIEdgeInsetsMake(5, 5, 5, 5);
    layout.headerHeight = 5;
    layout.footerHeight = 5;
    layout.minimumColumnSpacing = 5;
    layout.minimumInteritemSpacing = 5;
    [self configurelayout:layout];

    _collectionView = [[MHCollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
    _collectionView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    _collectionView.dataSource = self;
    _collectionView.delegate = self;
    _collectionView.backgroundColor = [UIColor clearColor];
    _collectionView.showsVerticalScrollIndicator = NO;
    _collectionView.userInteractionEnabled = YES;
    [_collectionView registerClass:[UICollectionViewCell class]
        forCellWithReuseIdentifier:@"UICollectionCell"];
    [self.view addSubview:_collectionView];
    /// 占位符
    _collectionView.emptyDataSetDelegate = self;
    _collectionView.emptyDataSetSource = self;
    [_collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.mas_equalTo(UIEdgeInsetsZero);
    }];
    
//    self.collectionView = 
//    self.tableView = tableView;
    _collectionView.contentInset  = self.contentInset;
//    // 注册cell
//    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"UITableViewCell"];
    
    /// CoderMikeHe FIXED: 这里需要强制布局一下界面，解决由于设置了tableView的contentInset，然而contentOffset始终是（0，0）的bug 但是这样会导致 tableView 刷新一次，从而导致子类在 viewDidLoad 无法及时注册的cell，从而会有Crash的隐患
//        [self.collectionView layoutIfNeeded];
//        [self.collectionView setNeedsLayout];
//        [self.collectionView updateConstraintsIfNeeded];
//        [self.collectionView setNeedsUpdateConstraints];
//        [self.view layoutIfNeeded];
    
    /// 添加加载和刷新控件
    if (self.viewModel.shouldPullDownToRefresh) {
        /// 下拉刷新
        @weakify(self);
        [self.collectionView mh_addHeaderRefresh:^(MJRefreshNormalHeader *header) {
            /// 加载下拉刷新的数据
            @strongify(self);
            [self tableViewDidTriggerHeaderRefresh];
        }];
        [self.collectionView.mj_header beginRefreshing];
    }
    
    if (self.viewModel.shouldPullUpToLoadMore) {
        /// 上拉加载
        @weakify(self);
        [self.collectionView mh_addFooterRefresh:^(MJRefreshAutoNormalFooter *footer) {
            /// 加载上拉刷新的数据
            @strongify(self);
            [self tableViewDidTriggerFooterRefresh];
        }];
        
        /// 隐藏footer or 无更多数据
        RAC(self.collectionView.mj_footer, hidden) = [[RACObserve(self.viewModel, dataSource)
                                                  deliverOnMainThread]
                                                 map:^(NSArray *dataSource) {
                                                     @strongify(self)
                                                     NSUInteger count = dataSource.count;
                                                     if (count == 0) return @1;
//                                                     if (self.viewModel.shouldEndRefreshingWithNoMoreData) return @(0);
//                                                     return (count % self.viewModel.perPage)?@1:@0;
                                                     if (self.viewModel.shouldEndRefreshingWithNoMoreData) return @(0);
                                                     if (self.viewModel.dataSource.count < self.viewModel.perPage && self.viewModel.page == 1 ) return @(1);
                                                     return (count % self.viewModel.perPage || (self.viewModel.requstDataCount ==count && self.viewModel.page != 1))?@1:@0;
                                                 }];
        
    }
    
    
    if (@available(iOS 11.0, *)) {
        MHAdjustsScrollViewInsets_Never(self.collectionView);
    }
}


- (UIImage *)imageForEmptyDataSet:(UIScrollView *)scrollView
{
    return [UIImage imageNamed:@"globle_emptyData"];
}


- (UIColor *)backgroundColorForEmptyDataSet:(UIScrollView *)scrollView
{
    return [UIColor whiteColor];
}


- (BOOL)emptyDataSetShouldAllowScroll:(UIScrollView *)scrollView {
    return YES;
}

- (NSAttributedString *)titleForEmptyDataSet:(UIScrollView *)scrollView
{
    NSString *text = @"暂无数据";
    
    NSDictionary *attributes = @{NSFontAttributeName: MHRegularFont_15,
                                 NSForegroundColorAttributeName: MHMetionTextColor};
    
    return [[NSAttributedString alloc] initWithString:text attributes:attributes];
}

- (CAAnimation *)imageAnimationForEmptyDataSet:(UIScrollView *)scrollView
{
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath: @"transform"];
    
    animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
    animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2, 0.0, 0.0, 1.0)];
    
    animation.duration = 0.25;
    animation.cumulative = YES;
    animation.repeatCount = MAXFLOAT;
    
    return animation;
}

#pragma mark - 上下拉刷新事件
/// 下拉事件
- (void)tableViewDidTriggerHeaderRefresh{
    @weakify(self)
//    NSDate* tmpStartData = [NSDate date];
   
    [[[self.viewModel.requestRemoteDataCommand
       execute:@1]
     	deliverOnMainThread]
    	subscribeNext:^(id x) {
            @strongify(self)
            self.viewModel.page = 1;
         
            /// 重置没有更多的状态
            if (self.viewModel.shouldEndRefreshingWithNoMoreData) [self.collectionView.mj_footer resetNoMoreData];
            self.collectionView.mj_footer.hidden = self.viewModel.dataSource.count < self.viewModel.perPage;
              [self.collectionView.mj_header endRefreshing];
        } error:^(NSError *error) {
            @strongify(self)
            /// 已经在bindViewModel中添加了对viewModel.dataSource的变化的监听来刷新数据,所以reload = NO即可
            [self.collectionView.mj_header endRefreshing];
        } completed:^{
            @strongify(self)
            /// 已经在bindViewModel中添加了对viewModel.dataSource的变化的监听来刷新数据,所以只要结束刷新即可
            [self.collectionView.mj_header endRefreshing];
            /// 请求完成
            [self _requestDataCompleted];
//            double deltaTime = [[NSDate date] timeIntervalSinceDate:tmpStartData];
//            NSLog(@"cost time = %f", deltaTime);
        }];
}

/// 上拉事件
- (void)tableViewDidTriggerFooterRefresh{
    @weakify(self);
//     NSDate* tmpStartData = [NSDate date];
    self.viewModel.requstDataCount = self.viewModel.dataSource.count;
    [[[self.viewModel.requestRemoteDataCommand
       execute:@(self.viewModel.page + 1)]
      deliverOnMainThread]
     subscribeNext:^(id x) {
         @strongify(self)
         self.viewModel.page += 1;
//         double deltaTime = [[NSDate date] timeIntervalSinceDate:tmpStartData];
//          NSLog(@"subscribeNext = %f", deltaTime);
          [self.collectionView.mj_footer endRefreshing];
     } error:^(NSError *error) {
         @strongify(self);
         [self.collectionView.mj_footer endRefreshing];
         if (error.code == 3) {
             self.collectionView.mj_footer.hidden = YES;
         }
         
     } completed:^{
         @strongify(self)
         [self.collectionView.mj_footer endRefreshing];
         /// 请求完成
         [self _requestDataCompleted];
//         double deltaTime = [[NSDate date] timeIntervalSinceDate:tmpStartData];
//         NSLog(@"cost time = %f", deltaTime);
     }];
}


#pragma mark - sub class can override it
- (UIEdgeInsets)contentInset{
    return UIEdgeInsetsMake(MH_APPLICATION_TOP_BAR_HEIGHT, 0, 0, 0);
}

/// reload tableView data
- (void)reloadData{

    [self.collectionView reloadData];
    
}


- (void)preloadDataWithCurrentIndex:(NSInteger)currentIndex{
    NSInteger totalCount = self.viewModel.dataSource.count;
    if ([self isSatisfyPreloadDataWithTotalCount:totalCount currentIndex:currentIndex]) {
        if (!self.collectionView.mj_footer.hidden) {
            [self tableViewDidTriggerFooterRefresh];
        }
    }
}

- (BOOL)isSatisfyPreloadDataWithTotalCount:(NSInteger)totalCount currentIndex:(NSInteger)currentIndex{
    //    NSLog(@"currentIndex self.viewModel.dataSource.count == %lu",currentIndex % self.viewModel.dataSource.count);
    
    return  ((currentIndex == totalCount - PreloadMinCount) && (currentIndex >= PreloadMinCount));
}

/// configure cell data
- (void)configureCell:(UICollectionViewCell *)cell atIndexPath:(NSIndexPath *)indexPath withObject:(id)object {}

- (void)configurelayout:(CHTCollectionViewWaterfallLayout *) layout{};


- (UICollectionViewCell *)collectionView:(MHCollectionView *)collectionView dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath
{
    return [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
}

#pragma mark - 辅助方法
- (void)_requestDataCompleted{
//    NSUInteger count = self.viewModel.dataSource.count;
    /// CoderMikeHe Fixed: 这里必须要等到，底部控件结束刷新后，再来设置无更多数据，否则被叠加无效
//    NSLog(@"self.viewModel.dataSource.count - self.viewModel.requstDataCount = %d",self.viewModel.dataSource.count - self.viewModel.requstDataCount);
    
    
//    if (!self.viewModel.shouldEndRefreshingWithNoMoreData && (self.viewModel.requstDataCount == count || (self.viewModel.dataSource.count - self.viewModel.requstDataCount) < self.viewModel.perPage ) ) {[
//                                                                                                                      self.collectionView.mj_footer endRefreshingWithNoMoreData
//                                                                                                                      ];
//     self.collectionView.mj_footer.hidden = YES;
//    }
    
    
//    [self.collectionView layoutIfNeeded];
//    [self.collectionView setNeedsLayout];
//    [self.collectionView updateConstraintsIfNeeded];
//    [self.collectionView setNeedsUpdateConstraints];
//    [self.view layoutIfNeeded];
}



#pragma mark - UICollectionViewDataSource

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    if (self.viewModel.shouldMultiSections) return [self.viewModel.dataSource[section] count];
    return self.viewModel.dataSource.count;
}

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    
    if (self.viewModel.shouldMultiSections) return self.viewModel.dataSource ? self.viewModel.dataSource.count : 0;
    return 1;
}

- (UICollectionViewCell *)collectionView:(MHCollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    
//     [self col]
//    UITableViewCell *cell = [self tableView:tableView dequeueReusableCellWithIdentifier:@"UITableViewCell" forIndexPath:indexPath];
     UICollectionViewCell *cell =  [self collectionView:collectionView dequeueReusableCellWithIdentifier:@"UICollectionCell" forIndexPath:indexPath];

        id object = nil;
        if (self.viewModel.shouldMultiSections) object = self.viewModel.dataSource[indexPath.section][indexPath.row];
        if (!self.viewModel.shouldMultiSections) object = self.viewModel.dataSource[indexPath.row];
    
        /// bind model
        [self configureCell:cell atIndexPath:indexPath withObject:(id)object];
        [self preloadDataWithCurrentIndex:self.viewModel.shouldMultiSections ? indexPath.section : indexPath.row];
        return cell;
}


#pragma mark - CHTCollectionViewDelegateWaterfallLayout
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    return CGSizeMake(40, 40);
}

-(void) collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    [collectionView deselectItemAtIndexPath:indexPath animated:YES];
    [self.viewModel.didSelectCommand execute:indexPath];
}

-(void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];
    [self.collectionView setNeedsLayout];
    [self.collectionView layoutIfNeeded];
}

@end
